package com.xl.basic.service.impl;

import cn.hutool.core.bean.BeanUtil;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xl.basic.entity.Result;
import com.xl.basic.entity.ResultEnums;
import com.xl.basic.entity.SPage;
import com.xl.basic.entity.param.AddRoleParam;
import com.xl.basic.entity.param.QueryRoleParam;

import com.xl.basic.entity.param.UpdRoleParam;
import com.xl.basic.entity.UserInfo;
import com.xl.basic.service.RoleService;
import com.xl.dao.domain.XlRole;
import com.xl.dao.domain.XlRoleMenu;
import com.xl.dao.domain.XlRoleUser;

import com.xl.dao.mapper.XlRoleMapper;
import com.xl.dao.mapper.XlRoleMenuMapper;
import com.xl.dao.mapper.XlRoleUserMapper;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author 钟勇
 * Create in 2023/8/29 16:06
 */
@Service
@RequiredArgsConstructor
public class RoleServiceImpl implements RoleService {
    private final XlRoleMapper roleMapper;
    private final XlRoleMenuMapper roleMenuMapper;
    private final XlRoleUserMapper roleUserMapper;


    @Override
    public Result<Object> addRole(@NonNull AddRoleParam param, UserInfo operator) {
        if (roleMapper.selectCount(new LambdaQueryWrapper<XlRole>()
                .eq(XlRole::getTitle, param.getTitle())
                .eq(XlRole::getState, 1)
        ) > 0) {
            return ResultEnums.BusinessError.getResult("角色名已存在");
        }

        if (StrUtil.isNotBlank(param.getRoleSign())) {
            if (roleMapper.selectCount(new LambdaQueryWrapper<XlRole>()
                    .eq(XlRole::getRoleSign, param.getRoleSign())
                    .eq(XlRole::getState, 1)
            ) > 0) {
                return ResultEnums.BusinessError.getResult("角色标识已存在");
            }
        }

        XlRole role = BeanUtil.copyProperties(param, XlRole.class);
        role.setBasicFlag(1 == role.getBasicFlag() ? 1 : 0)
                .setState(1)
                .setAddTime(LocalDateTime.now())
                .setAddUser(operator == null ? null : operator.getUserId());
        if (roleMapper.insert(role) <= 0) {
            return ResultEnums.Exception.getResult("角色写入失败");
        }

        return ResultEnums.Success.getResult();
    }

    @Override
    public Result<Object> updRole(@NonNull UpdRoleParam param, UserInfo operator) {
        XlRole xlRole = roleMapper.selectById(param.getRoleId());
        if (xlRole == null || xlRole.getState() != 1) {
            return ResultEnums.BusinessError.getResult("未找到对应角色");
        }

        //基础角色无法编辑
        if (xlRole.getBasicFlag() == 1) {
            return ResultEnums.BusinessError.getResult("基础角色无法编辑");
        }

        if (roleMapper.selectCount(new LambdaQueryWrapper<XlRole>()
                .ne(XlRole::getRoleId, param.getRoleId())
                .eq(XlRole::getTitle, param.getTitle())
                .eq(XlRole::getState, 1)
        ) > 0) {
            return ResultEnums.BusinessError.getResult("角色名已存在");
        }

        if (roleMapper.updateById(BeanUtil.copyProperties(param, XlRole.class)) <= 0) {
            return ResultEnums.Exception.getResult("角色编辑失败");
        }

        return ResultEnums.Success.getResult();
    }

    @Override
    public Result<Object> delRole(@NonNull Integer roleId, UserInfo operator) {
        XlRole xlRole = roleMapper.selectById(roleId);
        if (xlRole == null || xlRole.getState() != 1) {
            return ResultEnums.Success.getResult();
        }

        //基础角色无法移除
        if (xlRole.getBasicFlag() == 1) {
            return ResultEnums.BusinessError.getResult("基础角色无法删除");
        }

        if (roleMenuMapper.selectCount(new LambdaQueryWrapper<XlRoleMenu>()
                .eq(XlRoleMenu::getState, 1)
                .eq(XlRoleMenu::getRoleId, roleId)
        ) > 0) {
            return ResultEnums.BusinessError.getResult("角色有绑定菜单，请先清空");
        }

        if (roleUserMapper.selectCount(new LambdaQueryWrapper<XlRoleUser>()
                .eq(XlRoleUser::getState, 1)
                .eq(XlRoleUser::getRoleId, roleId)
        ) > 0) {
            return ResultEnums.BusinessError.getResult("角色有绑定用户，请先清空");
        }

        if (roleMapper.updateById(new XlRole()
                .setRoleId(roleId)
                .setState(0)
                .setUpdTime(LocalDateTime.now())
                .setUpdUser(operator == null ? null : operator.getUserId())
        ) <= 0) {
            return ResultEnums.Exception.getResult("角色删除失败");
        }

        return ResultEnums.Success.getResult();
    }

    @Override
    public Result<List<XlRole>> queryRoleList(@NonNull QueryRoleParam param) {
        List<XlRole> list = roleMapper.selectList(getQueryWrapper(param));
        return ResultEnums.Success.getListResult(list);
    }

    @Override
    public Result<List<XlRole>> queryRolePage(@NonNull QueryRoleParam param, SPage sPage) {
        Page<XlRole> page = roleMapper.selectPage(SPage.getPage(sPage), getQueryWrapper(param));
        return ResultEnums.Success.getPageResult(page);
    }

    private Wrapper<XlRole> getQueryWrapper(@NonNull QueryRoleParam param) {
        LambdaQueryWrapper<XlRole> wrapper = new LambdaQueryWrapper<XlRole>()
                .eq(XlRole::getState, 1);

        if (StrUtil.isNotBlank(param.getTitleLike())) {
            wrapper.like(XlRole::getTitle, param.getTitleLike());
        }

        if (StrUtil.isNotBlank(param.getUserId())) {
            wrapper.exists("""
                    SELECT 1 FROM xl_role_user WHERE state=1
                    AND role_id = xl_role.role_id
                    AND user_id = {0}
                    """, param.getUserId());
        }

        if (param.getBasicFlag() != null) {
            wrapper.eq(XlRole::getBasicFlag, param.getBasicFlag() ? 1 : 0);
        }

        if (StrUtil.isNotBlank(param.getUserLike())) {
            wrapper.exists("""
                    SELECT 1 FROM xl_role_user ru
                    INNER JOIN xl_user u ON u.state = 1 AND u.user_id = ru.user_id
                    WHERE ru.state = 1
                    AND ru.role_id = xl_role.role_id
                    AND (u.user_name like concat('%',{0},'%') OR u.email like concat('%',{0},'%') OR u.phone like concat('%',{0},'%'))
                    """, param.getUserLike());

        }

        wrapper.orderByDesc(XlRole::getAddTime);

        return wrapper;


    }
}
